/* 
 * File:   params.cpp
 * Author: Patrick W. M. Adams
 * Institution: Astrophysics, Cosmology and Gravity Centre,
 *              Department of Mathematics and Applied Mathematics,
 *              University of Cape Town
 *
 * Created on 14 March 2012, 4:03 AM
 */

#include "params.h"

//default constructor
Params::Params(bool readFromInternalLists){
    
    //check whether to read from internal lists or not
    if(readFromInternalLists){
        
        std::cout << "Reading from internal lists.." << std::endl;
    
        /* std::string i = "cvsid,ip,xyz0,xyz1,Lxyz,lperi,lshift_origin,coord_system,";
        i += "lequidist,coeff_grid,zeta_grid0,grid_func,xyz_star,lwrite_ic,";
        i += "lnowrite,luniform_z_mesh_aspect_ratio,unit_system,unit_length,";
        i += "lmodify,modify_filename,unit_velocity,unit_density,";
        i += "unit_temperature,unit_magnetic,c_light,G_Newton,hbar,random_gen,";
        i += "seed0,nfilter,lserial_io,der2_type,lread_oldsnap,";
        i += "lread_oldsnap_nomag,lread_oldsnap_nopscalar,";
        i += "lread_oldsnap_notestfield,lread_oldsnap_notestscalar,lread_aux,";
        i += "lwrite_aux,pretend_lnTT,lprocz_slowest,lcopysnapshots_exp,bcx,";
        i += "bcy,bcz,r_int,r_ext,r_ref,rsmooth,r_int_border,r_ext_border,mu0,";
        i += "force_lower_bound,force_upper_bound,tstart,lseparate_persist,";
        i += "fbcx1,fbcx2,fbcx1_2,fbcx2_2,fbcy1,fbcy2,fbcy1_1,fbcy1_2,";
        i += "fbcy2_1,fbcy2_2,fbcz1,fbcz2,fbcz1_1,fbcz1_2,fbcz2_1,fbcz2_2,";
        i += "fbcx_bot,fbcx_top,fbcy_bot,fbcy_top,fbcz_bot,fbcz_top,xyz_step,";
        i += "xi_step_frac,xi_step_width,dxi_fact,trans_width,";
        i += "lcylinder_in_a_box,lsphere_in_a_box,llocal_iso,init_loops,";
        i += "lwrite_2d,lcylindrical_gravity,border_frac_x,border_frac_y,";
        i += "border_frac_z,lborder_hyper_diff,luse_latitude,lshift_datacube_x,";
        i += "lfargo_advection,yequator,lequatory,lequatorz,zequator,lav_smallx,";
        i += "xav_max,niter_poisson,lconst_advection,u0_advec"; */
    
        /* std::string r = "cvsid,ip,nt,it1,it1d,dt,cdt,ddt,cdtv,cdtv2,cdtv3,cdts,";
        r += "cdtc,isave,itorder,dsnap,d2davg,dvid,dsound,dtmin,dspec,tmax,iwig,";
        r += "awig,ialive,max_walltime,dtmax,ldt_paronly,vel_spec,mag_spec,";
        r += "uxy_spec,bxy_spec,jxbxy_spec,xy_spec,oo_spec,cdtr,";
        r += "uxj_spec,vec_spec,ou_spec,ab_spec,azbz_spec,ub_spec,";
        r += "vel_phispec,mag_phispec,";
        r += "uxj_phispec,vec_phispec,ou_phispec,ab_phispec,EP_spec,ro_spec,";
        r += "TT_spec,ss_spec,cc_spec,cr_spec,isaveglobal,lr_spec,r2u_spec,";
        r += "r3u_spec,rhocc_pdf,cc_pdf,lncc_pdf,gcc_pdf,lngcc_pdf,kinflow,";
        r += "lkinflow_as_aux,ampl_kinflow_x,ampl_kinflow_y,ampl_kinflow_z,";
        r += "kx_kinflow,ky_kinflow,kz_kinflow,dtphase_kinflow,";
        r += "random_gen,der2_type,lrmwig_rho,lrmwig_full,lrmwig_xyaverage,";
        r += "ltime_integrals,lnowrite,noghost_for_isave,lwrite_yaverages,";
        r += "lwrite_zaverages,lwrite_phiaverages,lwrite_slices,";
        r += "lread_oldsnap_nomag,lread_oldsnap_nopscalar,test_nonblocking,";
        r += "lread_oldsnap_notestfield,lread_oldsnap_notestscalar,";
        r += "lread_aux,comment_char,ix,iy,iz,iz2,iz3,iz4,slice_position,";
        r += "xbot_slice,xtop_slice,ybot_slice,ytop_slice,zbot_slice,ztop_slice,";
        r += "bcx,bcy,bcz,r_int,r_ext,r_int_border,";
        r += "r_ext_border,lfreeze_varsquare,lfreeze_varint,lfreeze_varext,";
        r += "xfreeze_square,yfreeze_square,rfreeze_int,rfreeze_ext,wfreeze,";
        r += "wfreeze_int,wfreeze_ext,wborder,wborder_int,wborder_ext,tborder,";
        r += "fshift_int,fshift_ext,lsfflux,";
        r += "lreset_tstart,tstart,lseparate_persist,";
        r += "fbcx1,fbcx2,fbcx1_2,fbcx2_2,lpencil_check_diagnos_opti,";
        r += "fbcy1,fbcy2,fbcy1_1,fbcy1_2,fbcy2_1,fbcy2_2,";
        r += "fbcz1,fbcz2,fbcz1_1,fbcz1_2,fbcz2_1,fbcz2_2,";
        r += "fbcx_bot,fbcx_top,fbcy_bot,fbcy_top,fbcz_bot,fbcz_top,";
        r += "Udrift_bc,ttransient,tavg,idx_tavg,lserial_io,nr_directions,";
        r += "lsfz2,lsfu,lsfb,lsfz1,";
        r += "lpdfu,lpdfb,lpdfz1,lpdfz2,";
        r += "onedall,pretend_lnTT,old_cdtv,lmaxadvec_sum,save_lastsnap,";
        r += "lwrite_aux,lwrite_dvar,force_lower_bound,force_upper_bound,";
        r += "oned,twod,lpoint,mpoint,npoint,lpoint2,mpoint2,npoint2,";
        r += "border_frac_x,border_frac_y,border_frac_z,";
        r += "lcylinder_in_a_box,lsphere_in_a_box,ipencil_swap,";
        r += "lpencil_requested_swap,lpencil_diagnos_swap,lpencil_check,";
        r += "lpencil_check_small,lrandom_f_pencil_check,";
        r += "lpencil_init,lwrite_2d,lbidiagonal_derij,lisotropic_advection,";
        r += "crash_file_dtmin_factor,niter_poisson,lADI,ltestperturb,eps_rkf,";
        r += "eps_stiff,timestep_scaling,lequatory,lequatorz,zequator,penc0,";
        r += "lini_t_eq_zero,lav_smallx,xav_max,ldt_paronly,lweno_transport,";
        r += "it_timing,har_spec,hav_spec,j_spec,jb_spec,lread_less,";
        r += "llsode,lsplit_second,nu_sts,lfargo_advection,lformat,ltec,";
        r += "ldynamical_diffusion,re_mesh,lconst_advection,u0_advec,";
        r += "loutput_varn_at_exact_tsnap,lstop_on_ioerror,mailaddress";
        //extra parameters --check where they come in!
        
        r += "cs0,gamma,rho0,inituu,ampluu,kx_uu,ky_uu,widthuu,urand,initlnrho";
        r += "widthlnrho,gravz_profile,z1,z2,zref,gravz,initss,widthss";
        r += "mpoly1,mpoly2,isothtop,cs2cool,mpoly0"; */
        
        std::string r = "induction,navier-stokes,continuity,entropy,";
        r += "xdim,ydim,zdim,xlim,ylim,zlim,h,dt,nt,nu,initA,initAampl";
        
        //std::cout << "Input params: " << i << std::endl;
        //std::cout << "\nRun params: " << r << std::endl;
        
        //split the internal strings into the parameter lists
        //boost::algorithm::split(initParamList, i, boost::algorithm::is_any_of(","));
        boost::algorithm::split(runParamList, r, 
                boost::algorithm::is_any_of(","));
        
        //display variable names
        //std::cout << "Input params:" << std::endl;
        //for(int j = 0; j < initParamList.size(); j++)
            //std::cout << initParamList[j] << std::endl;
        
        //std::cout << "\nRun params:" << std::endl;
        //for(int j = 0; j < runParamList.size(); j++)
            //std::cout << runParamList[j] << std::endl;
      
    } else{ //read params in from input files using IO class
        
        std::cout << "Reading from master files.." << std::endl;
        
        FileIO f;
        
        f.readParamFile(std::string("params/RunMaster"), runParamList);
        f.readParamFile(std::string("params/InputMaster"), initParamList);
        
        //display variable names
        //std::cout << "Input params:" << std::endl;
        //for(int j = 0; j < initParamList.size(); j++)
            //std::cout << initParamList[j] << std::endl;
        
        //std::cout << "\nRun params:" << std::endl;
        //for(int j = 0; j < runParamList.size(); j++)
            //std::cout << runParamList[j] << std::endl;
        
    }
    
    //initialise iterators
    //initItr = initParamList.begin();
    runItr = runParamList.begin();
    
}//end default constructor

//default destructor
Params::~Params(){
    
}//end destructor

//checkParam
void Params::checkParam(std::string usrParamFile,
        std::vector<std::string> &distList){
    
    //display variable names
        //std::cout << "Input params:" << std::endl;
        //for(int j = 0; j < initParamList.size(); j++)
            //std::cout << initParamList[j] << std::endl;
        
        //std::cout << "\nRun params:" << std::endl;
        //for(int j = 0; j < runParamList.size(); j++)
            //std::cout << runParamList[j] << std::endl;
    
    bool NotFoundInRun = true; //NotFoundInInit = true;
    
    std::vector<std::string> tempVec;
    
    //read user-supplied input params first
    FileIO f(usrParamFile);
        
    f.readFile(false, paramList);
    
    std::string output = "";
    
    //cycle through the user-supplied parameters and check if they are valid
    for(unsigned int i = 0; i < paramList.size(); i++){
        
        //output += "Checking " + paramList[i] + "...\n";
        
        boost::algorithm::trim(paramList[i]); //trim excess whitespace
        
        //std::cout << "Checking " << paramList[i] << "..." << std::endl;
        
        //search lists by brute force
        for(int j = 0; j < runParamList.size(); j++){
            
            //std::cout << "Comparing " << paramList[i] << " and " << runParamList[j] << "..." << std::endl;
            //output += "Comparing " + paramList[i] + " and " + runParamList[j] + "...\n";
            
            boost::algorithm::split(tempVec, paramList[i], 
                        boost::algorithm::is_any_of(":="));
            
            //copy elements over to v
            for(unsigned int k = 0; k < tempVec.size(); k++){
                    
                boost::algorithm::trim(tempVec[k]);
                                
            }
            
            
            //std::cout << "Comparing " << tempVec[0] << " and " << runParamList[j] << "..." << std::endl;
            
            if(tempVec[0] == runParamList[j]){
                
                NotFoundInRun = false;
                
                //copy elements over to v
                for(unsigned int k = 0; k < tempVec.size(); k++){
                            
                    distList.push_back(tempVec[k]);
                    
                    //std::cout << tempVec[k] << std::endl;
                                
                }
                
                //std::cout << paramList[i] << " was found in run list." << std::endl;
                //output += paramList[i] + " was found in run list.\n";
                break; //exit the loop -- param found
                
            }
            
        }
        
        /* for(int k = 0; k < initParamList.size(); k++){
            
            //std::cout << "Comparing " << paramList[i] << " and " << initParamList[k] << "..." << std::endl;
            //output += "Comparing " + paramList[i] + " and " + initParamList[k] + "...\n";
            
            if(paramList[i] == initParamList[k]){
                
                NotFoundInInit = false;
                
                //std::cout << paramList[i] << " was found in init list." << std::endl;
                output += paramList[i] + " was found in init list.\n";
                break; //exit the loop -- param found
                
            }
            
        } */
        
        distList.push_back("$"); //insert a breaker into the distribution list
        
        //check if param was found
        if((NotFoundInRun == true)){ //and (NotFoundInInit == true)){
            
            std::cout << "Parameter " << paramList[i] << " is not valid!" << std::endl;
            //output += paramList[i] + " is invalid.\n";
            
        }
        
        NotFoundInRun = true;// NotFoundInInit = true; //reset 
        
    }
    
    f.writeFile(output,"paramCheckOut");
    
    std::cout << "\nParameters and values that were supplied:\n" << std::endl;
    
    //copy elements over to v
    for(unsigned int i = 0; i < distList.size(); i++){
        
        std::cout << distList[i] << std::endl;
                                
    }
    
}//end checkParam